package com.feilong.commons.core.security;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import com.feilong.commons.core.util.ByteUtil;
import com.feilong.commons.core.util.StringUtil;

/**
 * Md5加密
 * 
 * <pre>
 * 检验你的实现是否正确：
 * MD5Util.MD5Encode(&quot;&quot;) = d41d8cd98f00b204e9800998ecf8427e
 * MD5Util.MD5Encode(&quot;a&quot;) = 0cc175b9c0f1b6a831c399e269772661
 * MD5Util.MD5Encode(&quot;abc&quot;) = 900150983cd24fb0d6963f7d28e17f72
 * MD5Util.MD5Encode(&quot;message digest&quot;) = f96b697d7cb7938d525a2f31aaf161d0
 * MD5Util.MD5Encode(&quot;abcdefghijklmnopqrstuvwxyz&quot;) = c3fcd3d76192e4007dfb496cca67e13b
 * </pre>
 * 
 * @author 腾讯通
 * @author <a href="mailto:venusdrogon@163.com">金鑫</a>
 * @version 1.0 2010年10月26日 17:13:58
 * @version 1.1 2011-10-18 16:49
 * @since 1.0
 */
public final class MD5Util{

	private final static String	algorithm	= OnewayType.MD5.toString();

	/**
	 * private
	 */
	private MD5Util(){}

	/***************************************************************************/
	/**
	 * md5加密字符串
	 * 
	 * @param origin
	 *            原始字符串,将使用默认的 value.getBytes() 转成字节数组<br>
	 *            如果需要string 转码,请自行调用value.getBytes(string chartsetname),再调用{@link #encode(byte[])}
	 * @return 加密之后的转成小写的16进制字符串
	 */
	public final static String encode(String origin){
		byte[] inputBytes = StringUtil.toBytes(origin);
		return encode(inputBytes);
	}

	/**
	 * md5加密,byte[]
	 * 
	 * @param inputBytes
	 * @return 加密之后的转成小写的16进制字符串
	 */
	public final static String encode(byte[] inputBytes){
		MessageDigest messageDigest = getMessageDigest(algorithm);
		byte[] bs = messageDigest.digest(inputBytes);
		return ByteUtil.bytesToHexStringLowerCase(bs);
	}

	/***************************************************************************/
	/**
	 * 计算文件MD5值
	 * 
	 * @param filePath
	 *            文件
	 * @return
	 */
	public final static String encodeFile(String filePath){
		File file = new File(filePath);
		if (file.isFile()){
			try{
				FileInputStream fileInputStream = new FileInputStream(file);
				MessageDigest messageDigest = getMessageDigest(algorithm);
				byte buffer[] = new byte[1024];
				int len;
				while ((len = fileInputStream.read(buffer, 0, 1024)) != -1){
					messageDigest.update(buffer, 0, len);
				}
				fileInputStream.close();
				byte[] bs = messageDigest.digest();
				// 该数的正负号（-1 表示负，0 表示零，1 表示正）
				BigInteger bigInt = new BigInteger(1, bs);
				return bigInt.toString(16);
			}catch (FileNotFoundException e){
				e.printStackTrace();
			}catch (IOException e){
				e.printStackTrace();
			}
		}
		return null;
	}

	/***************************************************************************/
	/**
	 * 使用MD5创建MessageDigest对象
	 * 
	 * @return MessageDigest
	 */
	private static MessageDigest getMessageDigest(String algorithm){
		try{
			// 使用MD5创建MessageDigest对象
			MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
			return messageDigest;
		}catch (NoSuchAlgorithmException e){
			throw new IllegalArgumentException("No such algorithm [" + algorithm + "]");
		}
	}
}